#ifndef __tenacitas_interlace_text_core_coordinates_tester_h__
#define __tenacitas_interlace_text_core_coordinates_tester_h__

#include <iostream>
#include <cstdint>
#include <string>

#include "runtest.h"

#include <tenacitas.interlace_text.core/coordinates.h>
#include <tenacitas.interlace_text.core/coordinate.h>
#include <tenacitas.return_code.core/rc.h>

namespace tenacitas {
    namespace interlace_text {
        namespace core {

            class coordinates_tester {
            private:
                struct supplier {
                    struct interlace {};    
                    typedef std::string text;
                };

                static bool test1() {
                    std::cerr << "\n+++ coordiantes_tester::test1" << std::endl;

                    typedef core::coordinates<supplier> coordinates;
                    typedef typename coordinates::text text;

                    text _t("sorvete");

                    coordinates _c(_t);

                    std::cerr << _c << std::endl;

                    return true;
                }

                static bool test2() {
                    std::cerr << "\n+++ coordiantes_tester::test2" << std::endl;

                    typedef core::coordinates<supplier> coordinates;
                    typedef typename coordinates::text text;
                    typedef core::coordinate<supplier> coordinate;
                    

                    text _t("sorvete");

                    coordinates _cs(_t);

                    try {
                        
                        const coordinate & _c = _cs[2];

                        std::cerr << "[2] = " << _c.get_letter() << std::endl;
                    
                        return (_c.get_letter() == 'r');

                    } catch (rc<> & _rc) {
                        std::cerr << _rc.get_class_id() << ", " <<
                            _rc.get_constant_id() << std::endl;
                        return false;
                    }
                }

                static bool test3() {
                    std::cerr << "\n+++ coordiantes_tester::test3" << std::endl;

                    typedef core::coordinates<supplier> coordinates;
                    typedef typename coordinates::text text;
                    typedef core::coordinate<supplier> coordinate;

                    text _t("sorvete");

                    coordinates _cs(_t);

                    try {
                        
                        coordinate & _c = _cs[2];

                        std::cerr << "[2] before = " << _c.get_letter() <<
                            std::endl; 

                        _c.set_letter('Y');

                        std::cerr << "[2] after = " << _c.get_letter() <<
                            std::endl; 

                        return (_c.get_letter() == 'Y');

                    } catch (rc<> & _rc) {
                        std::cerr << _rc.get_class_id() << ", " <<
                            _rc.get_constant_id() << std::endl;
                        return false;
                    }
                }

                static bool test4() {
                    std::cerr << "\n+++ coordiantes_tester::test4" << std::endl;

                    typedef core::coordinates<supplier> coordinates;
                    typedef typename coordinates::text text;

                    text _t("sorvete");

                    coordinates _cs(_t);

                    try {
                        
                        std::cerr << "[2] before = " << _cs[2].get_letter() <<
                            std::endl; 

                        _cs[2].set_letter('Y');

                        std::cerr << "[2] after = " << _cs[2].get_letter() <<
                            std::endl; 

                        return (_cs[2].get_letter() == 'Y');

                    } catch (std::exception & _e) {
                        std::cerr << _e.what() << std::endl;
                        return false;
                    }
                }

                static bool test5() {
                    std::cerr << "\n+++ coordiantes_tester::test5" << std::endl;

                    typedef core::coordinates<supplier> coordinates;
                    typedef typename coordinates::text text;

                    text _t("sorvete");

                    coordinates _cs1(_t);
                    try {
                        std::cerr << _cs1[10].get_letter() << std::endl;
                        return false;
                    } catch (rc<> & _rc) {
                        std::cerr << _rc.get_class_id() << ", " <<
                            _rc.get_constant_id() << std::endl;
                        return true;
                    }
                }

                static bool test6() {
                    std::cerr << "\n+++ coordiantes_tester::test6" << std::endl;

                    typedef core::coordinates<supplier> coordinates;
                    typedef typename coordinates::text text;

                    text _t("sorvete");

                    coordinates _cs1(_t);
                    try {
                        std::cerr << _cs1[-4].get_letter() << std::endl;
                        return false;
                    } catch (std::exception & _e) {
                        std::cerr << _e.what() << std::endl;
                        return true;
                    }
                }

                static bool test8() {
                    std::cerr << "\n+++ coordiantes_tester::test8" << std::endl;

                    typedef core::coordinates<supplier> coordinates;
                    typedef typename coordinates::text text;

                    text _t1("sorvete");

                    coordinates _cs1(_t1);

                    return (_cs1.get_size() == 
                            static_cast<typename
                            coordinates::index>(_t1.size()));
                }

                static bool test9() {
                    std::cerr << "\n+++ coordiantes_tester::test9" << std::endl;

                    typedef core::coordinates<supplier> coordinates;
                    typedef typename coordinates::text text;

                    text _t1("sorvete");

                    coordinates _cs1(_t1);

                    return (!_cs1.is_positioned());
                    
                }

                static bool test10() {
                    std::cerr << "\n+++ coordiantes_tester::test10" << std::endl;

                    typedef core::coordinates<supplier> coordinates;
                    typedef typename coordinates::text text;

                    text _t1("sorvete");

                    coordinates _cs1(_t1);

                    _cs1[4].set_line(9);

                    return (!_cs1.is_positioned());
                    
                }
                
                static bool test11() {
                    std::cerr << "\n+++ coordiantes_tester::test11" << std::endl;

                    typedef core::coordinates<supplier> coordinates;
                    typedef typename coordinates::text text;

                    text _t1("sorvete");

                    coordinates _cs1(_t1);

                    _cs1[2].set_column(29);

                    return (!_cs1.is_positioned());
                }

                static bool test12() {
                    std::cerr << "\n+++ coordiantes_tester::test12" << std::endl;

                    typedef core::coordinates<supplier> coordinates;
                    typedef typename coordinates::text text;

                    text _t1("sorvete");

                    coordinates _cs1(_t1);

                    _cs1[2].set_column(29);
                    _cs1[2].set_line(6);

                    return (!_cs1.is_positioned());
                }

                static bool test13() {
                    std::cerr << "\n+++ coordiantes_tester::test13" << std::endl;

                    typedef core::coordinates<supplier> coordinates;
                    typedef typename coordinates::text text;

                    text _t1("sorvete");

                    coordinates _cs1(_t1);

                    typename coordinates::index _size = _cs1.get_size();
                    for (typename coordinates::index _i = 0;
                         _i < _size;
                         ++_i) {
                        if (_i != 0) {
                            _cs1[_i].set_column(29);
                            _cs1[_i].set_line(6);
                        }
                    }

                    return (!_cs1.is_positioned());
                }
                
                static bool test14() {
                    std::cerr << "\n+++ coordiantes_tester::test14" << std::endl;

                    typedef core::coordinates<supplier> coordinates;
                    typedef typename coordinates::text text;

                    text _t1("sorvete");

                    coordinates _cs1(_t1);

                    typename coordinates::index _size = _cs1.get_size();
                    for (typename coordinates::index _i = 0;
                         _i < _size;
                         ++_i) {
                        if (_i != _size - 1) {
                            _cs1[_i].set_column(29);
                            _cs1[_i].set_line(6);
                        }
                    }

                    std::cerr << _cs1 << std::endl;
                    
                    return (!_cs1.is_positioned());
                }

                static bool test15() {
                    std::cerr << "\n+++ coordiantes_tester::test15" << std::endl;

                    typedef core::coordinates<supplier> coordinates;
                    typedef typename coordinates::text text;

                    text _t1("sorvete");

                    coordinates _cs1(_t1);

                    typename coordinates::index _size = _cs1.get_size();
                    for (typename coordinates::index _i = 0;
                         _i < _size;
                         ++_i) {
                        if (_i != 5) {
                            _cs1[_i].set_column(29);
                            _cs1[_i].set_line(6);
                        }
                    }

                    std::cerr << _cs1 << std::endl;

                    return (!_cs1.is_positioned());
                }
                
                static bool test16() {
                    std::cerr << "\n+++ coordiantes_tester::test16" << std::endl;

                    typedef core::coordinates<supplier> coordinates;
                    typedef typename coordinates::text text;

                    text _t1("sorvete");

                    coordinates _cs1(_t1);

                    typename coordinates::index _size = _cs1.get_size();
                    for (typename coordinates::index _i = 0;
                         _i < _size;
                         ++_i) {
                        _cs1[_i].set_column(29);
                        _cs1[_i].set_line(6);
                    }

                    std::cerr << _cs1 << std::endl;

                    return (_cs1.is_positioned());
                }

                static bool test17() {
                    std::cerr << "\n+++ coordiantes_tester::test17" << std::endl;

                    typedef core::coordinates<supplier> coordinates;
                    typedef typename coordinates::text text;

                    text _t1("sorvete");

                    coordinates _cs1(_t1);

                    typename coordinates::index _size = _cs1.get_size();
                    for (typename coordinates::index _i = 0;
                         _i < _size;
                         ++_i) {
                        _cs1[_i].set_column(29);
                        _cs1[_i].set_line(6);
                    }

                    std::cerr << _cs1 << std::endl;

                    _cs1.unposition();

                    std::cerr << _cs1 << std::endl;

                    return (!_cs1.is_positioned());
                }
                
                static bool test18() {
                    std::cerr << "\n+++ coordiantes_tester::test18" << std::endl;

                    typedef core::coordinates<supplier> coordinates;
                    typedef typename coordinates::text text;

                    text _t1("sorvete");

                    coordinates _cs1(_t1);
                    std::cerr << _cs1 << std::endl;
                    
                    coordinates _cs2(_cs1);
                    std::cerr << _cs2 << std::endl;

                    typename coordinates::index _size = _cs1.get_size();
                    for (typename coordinates::index _i = 0;
                         _i < _size;
                         ++_i) {
                        if (_cs1[_i] != _cs2[_i]) {
                            return false;
                        }
                    }
                    return true;
                }

                static bool test19() {
                    std::cerr << "\n+++ coordiantes_tester::test19" << std::endl;

                    typedef core::coordinates<supplier> coordinates;
                    typedef typename coordinates::text text;

                    text _t1("sorvete");

                    coordinates _cs1(_t1);
                    std::cerr << _cs1 << std::endl;
                    
                    coordinates _cs2(_cs1);
                    std::cerr << _cs2 << std::endl;

                    return (_cs1 == _cs2);
                }

                static bool test20() {
                    std::cerr << "\n+++ coordiantes_tester::test20" << std::endl;

                    typedef core::coordinates<supplier> coordinates;
                    typedef typename coordinates::text text;

                    text _t1("sorvete");

                    coordinates _cs1(_t1);
                    std::cerr << _cs1 << std::endl;
                    
                    coordinates _cs2(_cs1);
                    std::cerr << _cs2 << std::endl;

                    _cs2[3].set_letter('P');
                    std::cerr << _cs2 << std::endl;

                    return (_cs1 != _cs2);
                }
                
                static bool test21() {
                    std::cerr << "\n+++ coordiantes_tester::test21" << std::endl;

                    typedef core::coordinates<supplier> coordinates;
                    typedef typename coordinates::text text;

                    text _t1("sorvete");

                    coordinates _cs1(_t1);
                    std::cerr << _cs1 << std::endl;
                    
                    coordinates _cs2 = _cs1;
                    std::cerr << _cs2 << std::endl;

                    _cs2[3].set_letter('P');
                    std::cerr << _cs2 << std::endl;

                    return (_cs1 != _cs2);
                } 
                
                static bool test22() {
                    std::cerr << "\n+++ coordiantes_tester::test22" << std::endl;

                    typedef core::coordinates<supplier> coordinates;
                    typedef typename coordinates::text text;

                    text _t1("sorvete");

                    coordinates _cs1(_t1);
                    std::cerr << _cs1 << std::endl;
                    
                    coordinates _cs2 = _cs1;
                    std::cerr << _cs2 << std::endl;

                    return (_cs1 == _cs2);
                }

            public:
                static void run() {
                    runtest(coordinates_tester::test1());
                    runtest(coordinates_tester::test2());
                    runtest(coordinates_tester::test3());
                    runtest(coordinates_tester::test4());
                    runtest(coordinates_tester::test5());
                    runtest(coordinates_tester::test6());
                    runtest(coordinates_tester::test8());
                    runtest(coordinates_tester::test9());
                    runtest(coordinates_tester::test10());
                    runtest(coordinates_tester::test11());
                    runtest(coordinates_tester::test12());
                    runtest(coordinates_tester::test13());
                    runtest(coordinates_tester::test14());
                    runtest(coordinates_tester::test15());
                    runtest(coordinates_tester::test16());
                    runtest(coordinates_tester::test17());
                    runtest(coordinates_tester::test18());
                    runtest(coordinates_tester::test19());
                    runtest(coordinates_tester::test20());
                    runtest(coordinates_tester::test21());
                    runtest(coordinates_tester::test22());
                }
            };

        }
    }
}

#endif
